home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
-
-
-
-
-
- MINT Tutorial
-
- This document assumes that you have loaded it into Tread using the
- editor supplied with Tread. You should read this document and try the
- examples that are given. You may use the arrow keys to view the rest of
- the document.
-
-
-
-
-
-
-
- Examples
-
- You will be asked to execute some of the example programs. Rather than
- force you to type the example in, a MINT program has been written which
- executes a MINT program directly from the text. This MINT program is
- appropriately called "try it". Try it will execute the program that
- appears on the line that the cursor is on. The result of the program,
- if any, will be displayed inside quotes on the last line of the screen.
-
- To try an example, position the cursor anywhere on the line containing
- the example and type the F1 key. What you have just done is to execute
- the try it program. Don't try to understand exactly how this works yet,
- just take for granted that it works. As The Great Wizard of Oz told
- Dorothy, "Pay no attention to the man behind the curtain."
-
-
-
- The Basics
-
- The basic organizing principle of MINT is this: Everything is a string,
- and strings are sequences of arbitrary characters. Therefore, programs
- are strings and data are strings (yes, data really is plural). The
- following example is a valid MINT program. It doesn't do anything, but
- it's valid.
-
- This is a valid MINT program.
-
- Notice that the result of executing the program is just the program
- itself. This is because MINT didn't find any functions to execute.
-
-
- A Single Function
-
- Now, for a more useful program, you need to know how MINT recognizes
- functions. A MINT function to add two numbers is given below. The two
- character sequence #( begins the function, ++ is the name of the
- function, and 5 and 7 are the arguments to the function, seperated by
- commas. The function adds both its arguments and returns the result as
- its value. Try this program in the same manner as before. You will find
- that execute is suggesting "try it". If this is what you want to do
- (and it is), then just type a return.
-
- The sum of five and seven is #(++,5,7).
-
- Notice that the MINT function is replaced by "12". This is how MINT
- evaluates its functions. When a function is recognized, the function is
- executed, and its invocation is replaced by its value.
-
-
- Multiple Functions
-
-
- Functions may be concatenated. Try the following example.
-
- #(++,1,1)#(++,2,2)
-
- You will discover that the result appears to be, and is, twenty four.
- This is because you concatenated the results of #(++,1,1) and #(++,2,2)
- to get a two and a four next to each other. Since MINT deals with strings,
- a two and a four becomes twenty four.
-
-
- Functions may be nested. Following the logic of the preceding example,
- nested functions are evaluated in the following manner: the function that
- is found first is executed first, and its invocation is replaced by its
- value. The next function to be found is executed, and its invocation is
- replaced by its value. Try the following example.
-
- #(**,3,#(++,5,7))
-
- Notice that the value is 36, which is three multipled by twelve.
-
-
- Recognizing Functions
-
- MINT recognizes functions by examining the input string character by
- character. A # followed by a ( is taken to be the beginning of a
- function. A , seperates arguments from each other. A ) causes a
- function to be recognized and evaluated. Let's try the following examples.
-
- #(an,Hello There)
-
- The "an" function causes its first argument to be placed on the bottom
- line of the screen.
-
- #(an,Hello There
-
- Leaving off the closing paren causes the function to execute improperly.
-
- #an,Hello There
-
- Leaving off the opening paren causes the function to execute improperly.
-
- (an,Hello There)
-
- Leaving off the sharp has a different, desirable effect. If the MINT
- scanner encounters an open paren, then all the characters to the next
- matching close paren are skipped. This is called protecting a string.
-
- (#(an,Hello There))
-
- Notice that the "an" function is not executed. This happens because
- those characters are passed over by the scanner.
-
- (#(**,2,#(++,5,7)))
-
- Watch what happens when we leave off a close paren.
-
- (#(**,2,#(++,5,7))
-
- We end up with the wrong thing being executed. Watch what happens with
- an extra close paren.
-
- (#(**,2,#(++,5,7))))
-
- Now nothing happens. Protection works only if the parentheses are
- balanced!
-
-
- There are more details concerning scanning, but we'll leave those for
- later.
-
-
- Strings
-
- Not unexpectedly, MINT lets you save strings under a given name. There
- are no restrictions on what you name a string. Obviously, there are
- certain characters that you should avoid including in a name, namely open
- paren, comma, and close paren, and a few others. Let's try an example.
- Let's define a string called "my test" and give it the value "this is a
- silly test string". This is an example of the define string function.
-
- #(ds,my test,this is a silly test string)
-
- Wow! You just defined a string! Big, fat, hairy deal. Defining a string
- is useless until you know how to get it back, which leads us to the next
- example. This is an example of the get string function.
-
- #(gs,my test)
-
- You don't always have to get the entire string. There is a pointer
- associated with every string. The gs function doesn't change it, but
- some of the following functions do. You can get the string one character
- at a time, and the pointer is advanced by one. Try this example several
- times.
-
- #(go,my test)
-
- Notice that you get the characters of "my test" in sequence, starting at
- the beginning. You might be wondering how to position the pointer back
- to the beginning. Well, the following example restores the string
- pointer.
-
- #(rs,my test)
-
- Now that you're back at the beginning, you're ready to get several
- characters, using the get n characters function. Following this
- example, the string pointer is positioned to the "s" of "is".
-
- #(gn,my test,6)
-
- You might be wondering what happens if you try to get more characters
- than are left following the string pointer.
-
- #(gn,my test,1000)
-
- You get all of them, and no more. There are no more characters left
- following the string pointer. What happens if you try to get one when
- there aren't any to get?
-
- #(go,my test,no more)
- #(gn,my test,1,no more)
-
- The second argument of get one and the third argument of get n is
- returned if there aren't any characters left to get.
-
- Well, you could probably search a string for a given substring using the
- above functions, but it would be too much work. A function is provided
- for just that purpose. The first match function finds the first match of
- the given string. To remind you of the value of "my test", let's
- redefine it.
-
- #(ds,my test,Another silly test)
- #(fm,my test,silly)
-
- The value of first match is the string up to the found string. The
- string pointer, however, is positioned after the last character of the
- found match. This is a nice property. Let's use it to get the contents
- of "my test" one word at a time by searching for the space between
- words. First, we'll restore the string pointer.
-
- #(rs,my test)
- #(fm,my test, )
- #(fm,my test, )
- #(fm,my test, )
-
- Aha! We didn't get the last word of "my test". Well, of course we didn't
- because there isn't any space following the word "test". We'll use this
- as an excuse to explain the great lie.
-
-
- The Great Lie
-
-
- I've been leading you down the primrose path. To make things simpler,
- I've insisted that there is only one type of function invocation. There
- are really two types of functions, active and neutral. The function you
- have been using all along is the active type of function. After this
- function has been scanned, recognized, and evaluated, its result is
- re-scanned. A neutral function's result is not re-scanned. An example
- is in order. Let's define a string with a function in it. Remember that
- we have to protect the function to keep it from being executed too soon.
-
- #(ds,my function,(#(an,Hello There)))
-
- Let's try to retrieve the string the same way that we did earlier.
-
- #(gs,my function)
-
- By watching carefully, you can see "Hello There" announced, to be
- replaced by two double quotes. This happens because "my function" is
- re-scanned, and MINT sees the "an" function. Let's try a neutral
- function. The double sharp means neutral, not active.
-
- ##(gs,my function)
-
- Now we're getting somewhere! What happens if we try a triple sharp?
- Maybe something else magical will happen?
-
- ###(gs,my function)
-
- Nope, no dice. The extra sharp is treated as just another character,
- just like the period in the next example.
-
- .##(gs,my function)
-
-
- Let's go back to the first match example. What were we doing? Oh yes,
- we were trying to get "my test" one word at a time. We ran into the
- difficulty of not having a blank at the end of "my test". We couldn't
- get the following example to work.
-
- #(fm,my test, )
-
- Well, rather than keep you in suspense, I'll give you the solution and
- explain it afterward.
-
- #(fm,my test, ,(#(gn,my test,100)))
-
- Ahhhh. Success at last. But why? Well, if first match doesn't find
- the string, it returns its third argument. The third argument in the
- previous example is the "gn" function, which will get as many as it can,
- up to the amount specified. This gets the last word in "my test".
-
- But wait... What if I hadn't wanted to rescan the result of the first
- match? Wouldn't the result be "#(gn,my test,100)"? Well, no, it
- wouldn't, because first match always rescans the third argument if that
- is what it returns. And the same goes for get one and get n.
-
-
- Testing
-
- So what good would a language be without testing? Not much good, so
- several types of testing are supplied. The first, equality, is
- demonstrated below.
-
- #(==,string,string,yes,no)
- #(==,strin,string,yes,no)
- #(==,string,strin,yes,no)
-
- Get the picture? Those examples are simple but not so useful. The
- following examples are useful but not so simple.
-
- #(==,string,string,(#(an,yes)),(#(an,no)))
- #(==,strin,string,(#(an,yes)),(#(an,no)))
- #(==,string,strin,(#(an,yes)),(#(an,no)))
-
- Now you understand why active functions exist. Most of your testing
- functions will be called actively. Other testing functions will be
- explained later. You're 75% of the way to writing real programs.
-
-
- Programs
-
- I can see that you're just itching to write your first program. So be
- it. A program is simply a string that is re-scanned. Let's write a
- really trivial program.
-
- #(ds,trivial,(#(==,a,b,yes,no)))
- #(gs,trivial)
-
- Oh boy! This is getting exciting! The get string function brought
- trivial in, rescanned it, found the equality, evaluated it, and returned
- "no". But before you get too pleased with yourself, check out the next
- example.
-
- #(trivial)
-
- Confusion! Where is the function name? Well, there is no function name,
- and MINT recognizes that fact. Rather than throw up its hands in disgust,
- MINT assumes that you want to execute "trivial" as a program, and
- essentially performs a get string function on "trivial". Yes, there are
- some minor differences, but they will be explained in the next section.
-
- Now that you know how to write programs, you'll want to pass parameters
- to them.
-
-
- Parameters
-
- Programs need parameters to be at all useful. So let's write a non
- trivial program, and give it parameters using the make parameter
- function. The second argument to make parameter is purposefully null.
- Its meaning will be explained later.
-
- #(ds,non trivial,(#(==,a,b,yes,no)))
- #(mp,non trivial,,a,b)
- #(non trivial,silly,test)
- #(non trivial,test,test)
-
- The action of make parameter is to search the specified string for each
- of make parameter's arguments, one at a time. Wherever a match is found,
- the string is removed and changed into a parameter. The third argument
- becomes the first parameter, the fourth argument becomes the second
- parameter, etc.
-
- The mysterious second parameter becomes the "zeroth" parameter. When a
- non-function call is found, such as the "non trivial" example above, the
- name of the string is substituted for the "zeroth" parameter. The use of
- this is explained later in the section on looping.
-
- Rather than use single characters, such as "a" and "b" used previously,
- we shall use arg1, arg2, arg3, etc. This helps arguments to stand out
- from the surrounding text.
-
- The "non trivial" program returns yes if its two parameters are equal,
- and no otherwise. Returning yes or no can be useful, but let's do
- something even more useful - return a function. Remember that we have to
- protect the parameters arg2 and arg3, otherwise they both will be evaluated
- before the equality function is evaluated. We also have to protect the
- functions that we are passing as parameters to null, otherwise they will
- get evaluated too soon.
-
- #(ds,null,(#(==,arg1,,(arg2),(arg3))))
- #(mp,null,,arg1,arg2,arg3)
- #(null,a,(#(an,Yes)),(#(an,No)))
- #(null,,(#(an,Yes)),(#(an,No)))
-
-
-
- Looping
-
- MINT doesn't have while loops, or repeat until loops, or for next loops,
- although you could write any of them if you wish. MINT has something
- which is better, called recursion. Observe the following program, but
- don't try it yet!
-
- #(ds,recurse,(#(an,arg1)#(recurse,#(++,arg1,1))))
- #(mp,recurse,,arg1)
- #(recurse,1)
-
- Notice that the program announces its parameter, and then calls itself
- (recurses) with one more than its argument. There's no provision for
- stopping! Fortunately, MINT allows you to break out of any running
- program with the break key (Z-100 uses Shift-Help, IBM-PC uses
- Ctrl-Prtsc). Ok, try the program. When you get bored, use the break key
- to abort the program.
-
- Clearly, we need to exercise more control over looping. Let's rewrite
- "recurse" so that it stops at 100.
-
- #(ds,recurse,(#(an,arg1)#(==,arg1,100,,(#(recurse,#(++,arg1,1))))))
- #(mp,recurse,,arg1)
- #(recurse,1)
-
- Recurse announces it argument, and checks for equality with 100. The
- value of the equality is null if we've gotten to 100, otherwise it's a
- recursive call to itself with one more than itself.
-
- Let's get really tricky and use the "zeroth parameter" referred to in the
- previous section on parameters. Notice that we are now using the second
- argument to make parameter.
-
- #(ds,recurse,(#(an,arg1)#(==,arg1,100,,(#(SELF,#(++,arg1,1))))))
- #(mp,recurse,SELF,arg1)
- #(recurse,1)
-
- When recurse is called, the SELF parameter is replaced by "recurse",
- so we are effectively doing the same thing as before. By using SELF, we
- make it obvious that recurse is recursing, and we avoid having to
- explicitly name it within itself. The advantage of this becomes apparent
- when you try to change the name of a function. The fewer places that the
- name appears, the easier it is to change.
-
-
- Math
-
- Math in MINT is performed on strings of digits. A number in MINT is
- considered to be all the digits at the end of a string. Try the
- following example.
-
- #(++,Boeing 707,Lockheed 40)
-
- You can see that the two numbers are added and their sum placed at the
- end of the first argument. The other four math operations work the same
- way. The only function whose meaning is not obvious is "%%", which means
- modulo.
-
-
- #(--,Boeing 707,Lockheed 40)
- #(**,Boeing 707,Lockheed 40)
- #(//,Boeing 707,Lockheed 40)
- #(%%,Boeing 707,Lockheed 40)
-
- Numeric tests are performed using the greater than function.
-
- #(g?,10,20,yes,no)
- #(g?,10,10,yes,no)
- #(g?,20,10,yes,no)
-
- Numeric conversions from one base to another are possible. The following
- examples convert 64 decimal to other bases.
-
- 64 decimal is #(bc,64,d,a) ASCII
- 64 decimal is #(bc,64,d,h) hex
- 64 decimal is #(bc,64,d,o) octal
- 64 decimal is #(bc,64,d,b) binary
-
- The same rules for decimal numbers apply to non-decimal numbers.
- Converting from one base to the same base is a simple way to remove the
- non-digit prefix string.
-
- #(bc,43210,b,b)
- #(bc,a9876,o,o)
- #(bc,cba98,d,d)
- #(bc,ihgfe,h,h)
-
-
- Base conversion provides a simple way to include a left or right paren in
- a program.
-
- ##(bc,40,d,a)
- ##(bc,41,d,a)
-
-
- Odds and Ends
-
- There are a few more functions to cover, most of which are interesting but
- not important enough to warrant their own section.
-
- The output string function outputs its argument to the screen. This is
- useful for sending escape sequences to the screen, and ringing the bell.
- Under no circumstances should it be used to send messages to the user.
- That is reserved for announce.
-
- #(os,)
-
- The halt function unconditionally exits the MINT interpreter. Usually
- you want to make sure that the editor, text buffers, etc are saved before
- you execute this function.
-
- #(hl -- you don't really want to try this)
-
- The number of characters function counts the number of characters in its
- first argument.
-
- #(nc,abcd)
-
- Several functions exist strictly for the use of debugging Tread itself.
- They are only mentioned so that they may be avoided.
-
- #(db -- you don't really want to try this)
- #(ts -- you don't really want to try this)
- #(tt -- you don't really want to try this)
-
- Date and time return the date and time. Ho hum.
-
- #(dt)
- #(tm)
-
- There are several functions pertaining to strings. The list strings
- function returns a list of the names of the strings that have already
- been defined. Each name is followed by a copy of the second argument.
- Only those names that begin with the third argument are listed. You
- may be surprised by the number of names listed. Remember that the editor
- that you are using right now is written in MINT.
-
- #(ls,/)
- #(ls,/,r)
-
- Suppose we wanted to see if a string existed. We could get the string
- and see if what we got wasn't null, but that fails for strings that exist
- and are null. Well, the name test function comes to our rescue.
-
- #(n?,some silly name that doesn't exist,yes,no)
- #(n?,recurse,yes,no)
-
- The second example works because we defined recurse earlier.
-
- Just as strings may be defined, they may be erased using erase string.
- Erase string may have any number of arguments.
-
- #(ds,foobar,this is foobar)
- #(n?,foobar,y,n)
- #(es,foobar)
- #(n?,foobar,y,n)
-
- Just for grins, puzzle out what the following example would do.
-
- #(es -- don't do it,#(ls,(,)))
-
- Strings may be saved to and loaded from disk using save library and load
- library. Remember the recurse program we wrote long ago? Let's save it
- and my test into a temporary file. Save library may have any number of
- arguments.
-
- #(sl,mine.tmp,recurse,my test)
-
- If we ever want to load them back, we would use load library. All the
- strings stored in the file are loaded.
-
- #(ll,mine.tmp)
-
- Strings may be compared for alphabetic ordering.
-
- #(a?,abcd,abce,yes,no)
- #(a?,abcd,abcde,yes,no)
- #(a?,abce,abcd,yes,no)
- #(a?,abcde,abcd,yes,no)
- #(a?,abcd,abcd,yes,no)
-
- A single character may be input using input character. Try the following
- example and press any character.
-
- #(ic)
-
- You may also wish to wait a specified time for a character to appear.
- The next example will wait for five seconds for a key to be pressed. If
- a key was pressed, then the key will be input. The check key function
- returns a null value if no key was pressed in the specified number of
- hundreths of a second. If a key was pressed, the key will be returned
- but not input. The next input character function will input the key.
-
- #(==,##(ck,500),,no key pressed,(##(ic)))
-
-
- Text Buffer
-
- The following functions deal with the text buffer.
-
- There is a dual representation of text in the text buffer. One is in
- memory, and the other is on the screen. The function which updates this
- mapping is called redisplay. You may try the following example if you
- wish, but since you are using Tread to view this text buffer, the screen
- already matches the memory.
-
- #(rd)
-
- Redisplay has other functions. If the first parameter is not null, then
- the current contents of the screen are thrown away, and the screen is
- entirely repainted. The second parameter gives the desired cursor
- position. The next examples move the cursor to the top, middle and
- bottom of the screen respectively.
-
- #(rd,,1)
- #(rd,,12)
- #(rd,,24)
-
-
- There are only three functions which change the text in the buffer. One
- of them is the read file function, which will be discussed later.
- Another is the insert string function. Watch what happens when the next
- example is executed.
-
- #(is,Hi!)
-
- The string "Hi!" should get inserted at the beginning of the example line.
-
- Yet another function to modify the buffer is the delete to mark function.
- But before we can try it, we need to introduce marks.
-
- Marks
-
- To solve the problem of moving around in the buffer, the concept of the
- mark was created. Do not confuse a MINT mark with a Tread mark. The
- Tread marks are defined in terms of MINT marks. A mark is a single ASCII
- character. There are two types of marks - system (predefined) and
- user (variable). The system marks are given below, and the user marks
- are discussed later.
-
- . The point.
- < The character to the left of the point.
- > The character to the right of the point.
- { The word to the left of the mark.
- } The word to the right of the mark.
- ^ The beginning of this line.
- $ The end of this line.
- * The character selected by the pick device.
- [ The beginning of the file.
- ] The end of the file.
-
- Now let's try an example. Position the cursor to the beginning of the
- next example line, and try it several times.
-
- #(sp,>)
-
- The cursor moves to the right once each time that you try it.
- Position the cursor to the end of the next example line and try it
- several times.
-
- #(sp,<)
-
- The cursor moves to the left once each time that you try it. Position
- the cursor anywhere in the next example and try it.
-
- #(sp,^)
-
- The cursor always moves to the beginning of the line. Position the
- cursor anywhere in the next example and try it.
-
- #(sp,$)
-
- The cursor always moves to the end of the line. We'll skip over the [
- and ] marks, since it's tedious to find this spot in the text again. You
- can imagine how they work, however.
-
-
- Now that you know how to put text into the buffer, you need to know how
- to read it out of the buffer. The read to mark function will return as
- its value the contents of the text buffer between the point and the
- specified mark. Position the cursor to various points on the next
- example line and try it. Notice that the function is a neutral call (Why?).
-
- ##(rm,$)
- ##(rm,^)
- ##(rm,>)
- ##(rm,<)
-
- Remember that I deferred talking about deleting text from the buffer?
- Now you'll learn how. The delete to mark function deletes the contents
- of the text buffer between the point and the specified mark.
-
- #(dm,$) position the cursor here >< and delete this.
- delete this >< #(dm,^)
- #(dm,>) position the cursor here >< and delete the left angle.
- #(dm,<) position the cursor here >< and delete the right angle.
-
-
- User Marks
-
- User marks come in two flavors, local and global. They are called local
- and global because they correspond to the high level language concepts of
- the same name. Global marks are always available, while only the current
- set of local marks are available. A local mark is used for saving the
- point while you go off and do something else. A global mark is used for
- saving the point to make it available to other functions.
-
- Global marks are allocated by using a negative argument to the pm function.
- This also destroys all local marks. We won't try an example right now,
- since the example would cause Tread to barf.
-
- @ through Z Global user marks.
- 0 through 9 Local user marks.
-
- User marks may be set using the set mark function. The following example
- sets the global mark @ to the beginning of the file.
-
- #(sm,@,[)
-
- The next example sets the same mark to the point. If the second argument
- is missing, it defaults to the point.
-
- #(sm,@)
-
- Earlier I referred to "words". There are two types of characters - "word"
- characters and non-"word" characters. Rather than hard code a character type
- into a program, a table is used. This table is simply a string that is 256
- characters long. The "word" bit is bit zero, so that if the 33 character of
- the syntax table string (which is "!") has an odd value, then "!" is considered
- to be a word character. This would be unusual. A more usual example would
- cause "_" to be a word character. The following example sets the string
- "Fsyntax" to be the syntax table.
-
- #(st,Fsyntax)
-
-
-
- "lp" - look pattern
- "lk" - look
-
-
-
- Files
-
- You can write a file from a buffer using the wf primitive. All the text
- between the point and the mark that you specify will be written to the named
- file. Position the cursor to the beginning of the example line and try it.
- The example will write a one line file containing itself.
-
- #(wf,test.tmp,$)
-
- You can read a file into a buffer using the rf primitive. If the result of rf
- is null, the file was read in successfully, otherwise the result of rf is a
- readable error message. Read in the file that was written in the previous
- example:
-
- #(rf,test.tmp)
-
- You have access to MS-DOS's directory using the ff primitive. The following
- example will list all the .ED files with a bar between them:
-
- #(ff,*.ed,|)
-
- You can rename MS-DOS files using the rn primitive. Let's rename the test file
- that we wrote previously:
-
- #(rn,test.tmp,test.$$$)
-
- Let's delete the test file with its new name:
-
- #(de,test.$$$)
-